const {ccclass, property} = cc._decorator;
import {SnakeBody} from "./SnakeBody"
import {Macros} from "./../Common/AppMacros"
@ccclass
export class Snake extends cc.Component {

    @property(cc.Prefab)
    bodyPrefab:cc.Prefab;

    
    public canMove:boolean  = true;
    public isAlive:boolean  = true;
    public targetDir:number     = 0;
    public skinType:number      = 10;
    public snakeScale:number    = 0.3;

    private _direction:number   = 0;
    private _length:number      = 0;
    private _updateScale:number = 1;
    private _speedRate:number   = 1;
    private _dx:number  = 0;
    private _dy:number  = 0;
    

    private _snakeHead:SnakeBody;
    private _bodyPosArr:cc.Vec2[]   = [];
    private _bodyArr:SnakeBody[]    = [];

    public onLoad() {
        // init logic

    }

    public start() {
    }

    public update() {
        this.move();
    }

    public initSnake(pos:cc.Vec2, type:number) {
        this.skinType = type;
        this.initSnakeHead(pos);
        for (var i = 0; i < 5; i++) {
            this.addSnakeBody();
        }
    }

    private initSnakeHead(pos:cc.Vec2) {
        let body:cc.Node = cc.instantiate(this.bodyPrefab);
        this._snakeHead = <SnakeBody>body.getComponent(SnakeBody);
        this._snakeHead.init(pos, -1, this.skinType, 0);
        this._snakeHead.setRotation( -this._direction * 180 / Math.PI - 90);
        this._snakeHead.setScale(this.snakeScale);
        body.parent = this.node;
        this._bodyArr.push(this._snakeHead);
        this._bodyPosArr.push(pos);
        let dis = cc.v2(Math.cos(this._direction), Math.sin(this._direction)).mulSelf(Macros.POINT_POINT_LENGTH / Macros.POINT_COUNT);
        for (let i = 1; i < Macros.POINT_COUNT; i++)
	    {
		    let bodyP = cc.pSub(this._bodyPosArr[this._bodyPosArr.length - 1], dis);
		    this._bodyPosArr.push(bodyP);
	    }
        this._length++;
    }

    public addSnakeBody() {
        if (this._bodyPosArr.length == 0) {
            return;
        }
        let point = cc.v2(0, 0);
        if (this._bodyPosArr.length >= 2) {
            let dis = cc.pSub(cc.v2(this._bodyPosArr[this._bodyPosArr.length - 1]), (this._bodyPosArr[this._bodyPosArr.length - 2]));
            for (var i = 0; i < Macros.POINT_COUNT; i++) {
                let bodyP = cc.pAdd(this._bodyPosArr[this._bodyPosArr.length - 1], dis);
                this._bodyPosArr.push(bodyP);
                if (i == 0)
                {
                    point = bodyP;
                }              
            }
        }
        let bodyNode:cc.Node = cc.instantiate(this.bodyPrefab);
        bodyNode.parent = this.node;
        let body:SnakeBody = <SnakeBody>bodyNode.getComponent(SnakeBody);
        body.init(point, -(this._bodyArr.length + 1), this.skinType, 1);
        body.setScale(this.snakeScale);
        this._bodyArr.push(body);
        this._length++;
    }

    private move() {
        if (!this.canMove || !this.isAlive) {
            return;
        }
        this.retateDirection();
        this._dx = Macros.POINT_POINT_LENGTH * this._updateScale * Math.cos(this._direction);
        this._dy = Macros.POINT_POINT_LENGTH * this._updateScale * Math.sin(this._direction);
        if (this._speedRate == 1) {
            this._bodyPosArr.unshift(cc.pAdd(this._snakeHead.getPos(), cc.v2(this._dx, this._dy)));
            this._bodyPosArr.pop();
        }
        let index = 0;
        this._bodyArr.forEach(function(body) {
            let bodyPos = this._bodyPosArr[index];
            body.setPos(bodyPos);
            index += Macros.POINT_COUNT;
        }, this);

    }

    private retateDirection() {
        let disDir = 0;
        if (this.targetDir != this._direction) {
            disDir = Math.abs(this.targetDir - this._direction);
            if (disDir <= Math.PI / 18 || disDir >= 35 * Math.PI / 18) {
                this._direction = this.targetDir;
            } else {
                let i = this.targetDir > this._direction ? 1 : -1;
                this._direction += Math.PI * i / 18;
            }
            if (this._direction < 0) {
                this._direction = 2 * Math.PI + this._direction;
            }else if (this._direction > 2 * Math.PI) {
                this._direction = this._direction - 2 * Math.PI;
            }
            
            this._snakeHead.setRotation(-this._direction * 180 / Math.PI - 90);
        }
    }


}
